home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / edit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-08  |  8.3 KB  |  285 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: edit.c,v 5.7 1993/05/08 20:25:33 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.7 $   $State: Exp $
  6.  *
  7.  *             Copyright (c) 1988-1992 USENET Community Trust
  8.  *             Copyright (c) 1986,1987 Dave Taylor
  9.  *******************************************************************************
  10.  * Bug reports, patches, comments, suggestions should be sent to:
  11.  *
  12.  *    Syd Weinstein, Elm Coordinator
  13.  *    elm@DSI.COM            dsinc!elm
  14.  *
  15.  *******************************************************************************
  16.  * $Log: edit.c,v $
  17.  * Revision 5.7  1993/05/08  20:25:33  syd
  18.  * Add sleepmsg to control transient message delays
  19.  * From: Syd
  20.  *
  21.  * Revision 5.6  1993/02/03  17:12:53  syd
  22.  * move more declarations to defs.h, including sleep
  23.  * From: Syd
  24.  *
  25.  * Revision 5.5  1993/01/20  03:37:16  syd
  26.  * Nits and typos in the NLS messages and corresponding default messages.
  27.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  28.  *
  29.  * Revision 5.4  1992/12/07  14:53:21  syd
  30.  * Fix typos in edit.c
  31.  * From: Bo.Asbjorn.Muldbak <bam@jutland.ColumbiaSC.NCR.COM>
  32.  *
  33.  * Revision 5.3  1992/11/26  00:46:13  syd
  34.  * changes to first change screen back (Raw off) and then issue final
  35.  * error message.
  36.  * From: Syd
  37.  *
  38.  * Revision 5.2  1992/11/14  21:53:49  syd
  39.  * When elm copies the temp mailbox back to the mail spool to resync or
  40.  * quit, it changes to the mailgroup before attempting to diddle in the
  41.  * mail spool, but when it copies the temp mailbox back to the mail spool
  42.  * after editing, it forgets to change to mailgroup.  This patch appears
  43.  * to work, but I haven't exhaustively checked for some path that leaves
  44.  * the gid set
  45.  * wrong.  From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  46.  *
  47.  * Revision 5.1  1992/10/03  22:58:40  syd
  48.  * Initial checkin as of 2.4 Release at PL0
  49.  *
  50.  *
  51.  ******************************************************************************/
  52.  
  53. /** This routine is for allowing the user to edit their current folder
  54.     as they wish.
  55.  
  56. **/
  57.  
  58. #include "headers.h"
  59. #include "s_elm.h"
  60. #include <errno.h>
  61.  
  62. extern int errno;
  63.  
  64. char   *error_description();
  65. long   bytes();
  66.  
  67. #ifdef ALLOW_MAILBOX_EDITING
  68.  
  69. static void copy_failed_emergency_exit(cur_folder, edited_file, linked)
  70. char *cur_folder, *edited_file;
  71. int linked;
  72. {
  73.     int err = errno;
  74.  
  75.     MoveCursor(LINES, 0);
  76.     Raw(OFF);
  77.  
  78.     if (linked)
  79.         MCprintf(catgets(elm_msg_cat, ElmSet, ElmCouldntLinkMailfile,
  80.             "\nCouldn't link %s to mail file %s!\n"),
  81.             edited_file, cur_folder);
  82.     else
  83.         MCprintf(catgets(elm_msg_cat, ElmSet, ElmCouldntCopyMailfile,
  84.             "\nCouldn't copy %s to mail file %s!\n"),
  85.             cur_folder, edited_file);
  86.  
  87.     printf(catgets(elm_msg_cat, ElmSet, ElmCheckOutMail,
  88.         "\nYou'll need to check out %s for your mail.\n"),
  89.         edited_file);
  90.     printf("** %s. **\n", error_description(err));
  91.     unlock();                    /* ciao!*/
  92.     emergency_exit();
  93. }
  94.  
  95. edit_mailbox()
  96. {
  97.     /** Allow the user to edit their folder, always resynchronizing
  98.         afterwards.   Due to intense laziness on the part of the
  99.         programmer, this routine will invoke $EDITOR on the entire
  100.         file.  The mailer will ALWAYS resync on the folder
  101.         even if nothing has changed since, not unreasonably, it's
  102.         hard to figure out what occurred in the edit session...
  103.  
  104.         Also note that if the user wants to edit their incoming
  105.         mailbox they'll actually be editing the tempfile that is
  106.         an exact copy.  More on how we resync in that case later
  107.         in this code.
  108.     **/
  109.  
  110.     FILE    *real_folder, *temp_folder;
  111.     char    edited_file[SLEN], buffer[SLEN];
  112.     int    len;
  113.  
  114.     if(folder_type == SPOOL) {
  115.       if(save_file_stats(cur_folder) != 0) {
  116.         error1(catgets(elm_msg_cat, ElmSet, ElmPermFolder,
  117.           "Problems saving permissions of folder %s!"), cur_folder);
  118.         Raw(ON);
  119.         if (sleepmsg > 0)
  120.         sleep(sleepmsg);
  121.         return(0);
  122.       }
  123.     }
  124.  
  125.     strcpy(edited_file,
  126.         (folder_type == NON_SPOOL ? cur_folder : cur_tempfolder));
  127.     if (edit_a_file(edited_file) == 0) {
  128.         return (0);
  129.     }
  130.  
  131.     if (folder_type == SPOOL) {    /* uh oh... now the toughie...  */
  132.  
  133.       if (bytes(cur_folder) != mailfile_size) {
  134.  
  135.          /* SIGH.  We've received mail since we invoked the editor
  136.         on the folder.  We'll have to do some strange stuff to
  137.             remedy the problem... */
  138.  
  139.          PutLine0(LINES, 0, catgets(elm_msg_cat, ElmSet, ElmWarnNewMailRecv,
  140.            "Warning: new mail received..."));
  141.          CleartoEOLN();
  142.  
  143.          if ((temp_folder = fopen(edited_file, "a")) == NULL) {
  144.            dprint(1, (debugfile,
  145.             "Attempt to open \"%s\" to append failed in %s\n",
  146.             edited_file, "edit_mailbox"));
  147.            set_error(catgets(elm_msg_cat, ElmSet, ElmCouldntReopenTemp,
  148.          "Couldn't reopen temp file. Edit LOST!"));
  149.            return(1);
  150.          }
  151.          /** Now let's lock the folder up and stream the new stuff
  152.          into the temp file... **/
  153.  
  154.          lock(OUTGOING);
  155.          if ((real_folder = fopen(cur_folder, "r")) == NULL) {
  156.            dprint(1, (debugfile,
  157.                "Attempt to open \"%s\" for reading new mail failed in %s\n",
  158.             cur_folder, "edit_mailbox"));
  159.            sprintf(buffer, catgets(elm_msg_cat, ElmSet, ElmCouldntOpenFolder,
  160.          "Couldn't open %s for reading!  Edit LOST!"), cur_folder);
  161.            set_error(buffer);
  162.            unlock();
  163.            return(1);
  164.          }
  165.          if (fseek(real_folder, mailfile_size, 0) == -1) {
  166.            dprint(1, (debugfile,
  167.             "Couldn't seek to end of cur_folder (offset %ld) (%s)\n",
  168.             mailfile_size, "edit_mailbox"));
  169.            set_error(catgets(elm_msg_cat, ElmSet, ElmCouldntSeekEnd,
  170.          "Couldn't seek to end of folder.  Edit LOST!"));
  171.            unlock();
  172.            return(1);
  173.          }
  174.  
  175.          /** Now we can finally stream the new mail into the tempfile **/
  176.  
  177.          while ((len = mail_gets(buffer, SLEN, real_folder)) != 0)
  178.            if (fwrite(buffer, 1, len, temp_folder) != len) {
  179.              copy_failed_emergency_exit(cur_folder, edited_file, FALSE);
  180.            }
  181.  
  182.          fclose(real_folder);
  183.          if (fclose(temp_folder)) {
  184.            copy_failed_emergency_exit(cur_folder, edited_file, FALSE);
  185.          }
  186.  
  187.         } else lock(OUTGOING);
  188.  
  189. #ifdef SAVE_GROUP_MAILBOX_ID
  190.              setgid(mailgroupid);
  191. #endif
  192.  
  193.        /* remove real mail_file and then
  194.         * link or copy the edited mailfile to real mail_file */
  195.  
  196.        (void)unlink(cur_folder);
  197.  
  198.        if (link(edited_file, cur_folder) != 0)  {
  199.          if (errno == EXDEV || errno == EEXIST) {
  200.            /* attempt to link across file systems */
  201.               if (copy(edited_file, cur_folder) != 0) {
  202.              copy_failed_emergency_exit(cur_folder, edited_file, FALSE);
  203.            }
  204.          } else {
  205.              copy_failed_emergency_exit(cur_folder, edited_file, TRUE);
  206.          }
  207.        }
  208.  
  209.        /* restore file permissions before removing lock */
  210.  
  211.        if(restore_file_stats(cur_folder) != 1) {
  212.          error1(catgets(elm_msg_cat, ElmSet, ElmProblemsRestoringPerms,
  213.            "Problems restoring permissions of folder %s!"), cur_folder);
  214.          Raw(ON);
  215.          if (sleepmsg > 0)
  216.         sleep(sleepmsg);
  217.        }
  218.  
  219. #ifdef SAVE_GROUP_MAILBOX_ID
  220.        setgid(groupid);
  221. #endif
  222.  
  223.        unlock();
  224.        unlink(edited_file);    /* remove the edited mailfile */
  225.        error(catgets(elm_msg_cat, ElmSet, ElmChangesIncorporated,
  226.          "Changes incorporated into new mail..."));
  227.  
  228.     } else
  229.       error(catgets(elm_msg_cat, ElmSet, ElmResyncingNewVersion,
  230.         "Resynchronizing with new version of folder..."));
  231.  
  232.     if (sleepmsg > 0)
  233.         sleep(sleepmsg);
  234.     ClearScreen();
  235.     newmbox(cur_folder, FALSE);
  236.     showscreen();
  237.     return(1);
  238. }
  239.  
  240. #endif
  241.  
  242. int
  243. edit_a_file(editfile)
  244. char *editfile;
  245. {
  246.     /** Edit a file.  This routine is used by edit_mailbox()
  247.         and edit_aliases_text().  It gets all the editor info
  248.         from the elmrc file.
  249.     **/
  250.  
  251.     char     buffer[SLEN];
  252.  
  253.     PutLine0(LINES-1,0, catgets(elm_msg_cat, ElmSet, ElmInvokeEditor,
  254.       "Invoking editor..."));
  255.  
  256.     if (strcmp(editor, "builtin") == 0 || strcmp(editor, "none") == 0) {
  257.       if (in_string(alternative_editor, "%s"))
  258.         sprintf(buffer, alternative_editor, editfile);
  259.       else
  260.         sprintf(buffer, "%s %s", alternative_editor, editfile);
  261.     } else {
  262.       if (in_string(editor, "%s"))
  263.         sprintf(buffer, editor, editfile);
  264.       else
  265.         sprintf(buffer, "%s %s", editor, editfile);
  266.     }
  267.  
  268.     Raw(OFF);
  269.  
  270.     if (system_call(buffer, SY_ENAB_SIGHUP) == -1) {
  271.       error1(catgets(elm_msg_cat, ElmSet, ElmProblemsInvokingEditor,
  272.         "Problems invoking editor %s!"), alternative_editor);
  273.       Raw(ON);
  274.       if (sleepmsg > 0)
  275.         sleep(sleepmsg);
  276.       return(0);
  277.     }
  278.  
  279.     Raw(ON);
  280.     /* a location not near the next request, so an absolute is used */
  281.     SetXYLocation(0, 40);
  282.  
  283.     return(1);
  284. }
  285.